package com.scaffold.springmvc.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;

import wangjg.commons.bean.BeanUtil;
import wangjg.commons.dao.BasicHibernateDAO;
import wangjg.commons.dao.HibernateConfigurationTools;
import wangjg.commons.dao.HibernateDAOHelper;
import wangjg.commons.page.Page;

/**
 * DAO层业务基类
 * @author wangjg
 *
 * @param <T> 实体类型
 * @param <ID> 主键类型
 */
public class BasicBizDAO<T, ID extends Serializable> extends BasicHibernateDAO<T, ID>{
	/**
	 * 修改部分属性
	 */
	public void update(final T entity) {
		Session session = this.getSession();
		session.evict(entity);
		
		String pkName = "id";
		ID pkValue = (ID)BeanUtil.getNestedProperty(entity, pkName);
		T old = (T) session.get(entity.getClass(), pkValue);
		
		List<String> ppList = BeanUtil.getDifferentProperties(old, entity);
		String[] pps = new String[ppList.size()];
		ppList.toArray(pps);
		this.update(entity, pkValue, pps);
	}
	
	public void update(final T entity, ID id, String[] ppa) {
		Object[] pva = new Object[ppa.length+1];
		for(int i=0;i<ppa.length;i++){
			String pp = ppa[i];
			Object pv = BeanUtil.getNestedProperty(entity, pp);
			pva[i] = pv;
		}
		
		pva[pva.length-1] = id;
		this.update(persistentClass.getSimpleName(), ppa, pva);
	}
	
	private String getPkName(Class clazz){
		String pkName = HibernateConfigurationTools.getPkColumnName(clazz);
		return pkName;
	}
	
	public T findById(ID id) {
		return this.get(id);
	}
	
	T findAndEvict(ID id) {
		T entity = this.get(id);
		if(entity!=null)
			this.getSession().evict(entity);
		return entity;
	}
	
	protected List findByCriteria(DetachedCriteria criteria){
		Criteria c = criteria.getExecutableCriteria(this.getSession());
		return c.list();
	}
	
	protected <O> List<O> findByCriteria(DetachedCriteria criteria, Page page){
		List<O> list = null;
		if(page==null){
			list = this.findByCriteria(criteria);
		}else{
			list = this.findByCriteria(criteria, page.getStartRow(), page.getPageSize());
			
			Long total = this.count(criteria);
			page.setRowTotal(total);
		}
		return list;
	}
	
	protected List findByCriteria(DetachedCriteria criteria, Integer firstResult, Integer maxResults){
		Criteria c = criteria.getExecutableCriteria(this.getSession());
		if (firstResult >= 0) {
			c.setFirstResult(firstResult);
		}
		if (maxResults > 0) {
			c.setMaxResults(maxResults);
		}
		return c.list();
	}
	
	private <N extends Number> N count(DetachedCriteria dCriteria){
		Criteria criteria = dCriteria.getExecutableCriteria(this.getSession());
		return HibernateDAOHelper.count(criteria);
	}

}

